
# 运行命令
# manim -pql a01\prime.py PrimeCheckExplanation
from manim import *

class PrimeCheckExplanation(Scene):
    def construct(self):
        # 标题
        title = Text("为什么质数的检查只需要做到平方根", font_size=36, color=BLUE)
        self.add(title.to_edge(UP))

        # 数学证明
        proof_text = Text("如果一个数 n 不是质数，那么它可以被两个数 a 和 b 相乘得到:", font_size=24)
        self.add(proof_text.next_to(title, DOWN))



# 运行命令
# manim -pql your_script.py PrimeCheckExplanation

class TrialDivision(Scene):
    def __init__(self, numbers_to_check=[31, 91], **kwargs):
        self.numbers_to_check = numbers_to_check
        super().__init__(**kwargs)

    def construct(self):
        # 显示标题
        title = Text("试除法判断质数", font_size=36).to_edge(UP)
        self.play(Write(title))
        self.wait(1)

        for number_to_check in self.numbers_to_check:
            self.check_prime(number_to_check)
            self.wait(2)

    def check_prime(self, number_to_check):
        # 显示要检查的数字
        number_text = Text(f"要检查的数字: {number_to_check}", font_size=24).to_edge(UP*3)
        self.play(Write(number_text))
        self.wait(1)

        # 显示检查步骤
        explanation = Text("检查是否能被小于等于平方根的质数整除", font_size=24).next_to(number_text, DOWN)
        self.play(Write(explanation))
        self.wait(1)

        # 计算平方根
        sqrt_value = int(number_to_check**0.5)
        sqrt_text = Text(f"平方根取整: {sqrt_value}", font_size=24).next_to(explanation, DOWN)
        self.play(Write(sqrt_text))
        self.wait(1)

        # 生成小于等于平方根的质数列表
        primes = self.generate_primes(sqrt_value)
        primes_text = Text(f"质数列表: {primes}", font_size=24).next_to(sqrt_text, DOWN)
        self.play(Write(primes_text))
        self.wait(1)

        # 检查质数
        is_prime = True
        check_group = VGroup()
        for prime in primes:
            check_text = Text(f"检查质数 {prime}", font_size=24).next_to(primes_text, DOWN)
            check_group.add(check_text)
            self.play(Write(check_text))
            if number_to_check % prime == 0:
                result_text = Text(f"{number_to_check} 能被 {prime} 整除, 不是质数", font_size=24).next_to(check_text, DOWN)
                check_group.add(result_text)
                self.play(Write(result_text))
                is_prime = False
                self.play(FadeOut(check_text), FadeOut(result_text))
                break
            else:
                result_text = Text(f"{number_to_check} 不能被 {prime} 整除", font_size=24).next_to(check_text, DOWN)
                check_group.add(result_text)
                self.play(Write(result_text))
            self.wait(1)
            self.play(FadeOut(check_text), FadeOut(result_text))
        # 最终结果
        final_result_text = Text(f"{number_to_check} 是质数" if is_prime else f"{number_to_check} 不是质数", font_size=24).next_to(primes_text, DOWN)
        self.play(Write(final_result_text))
        self.wait(2)
        # 直接去掉number_text等的文字，不使用FadeOut    
        self.play(FadeOut(number_text), FadeOut(explanation), FadeOut(sqrt_text), FadeOut(primes_text),FadeOut(final_result_text))
        for mob in check_group:
            self.remove(mob)

    def generate_primes(self, n):
        """生成小于等于 n 的所有质数"""
        sieve = [True] * (n + 1)
        sieve[0] = sieve[1] = False
        for start in range(2, int(n**0.5) + 1):
            if sieve[start]:
                for multiple in range(start*start, n + 1, start):
                    sieve[multiple] = False
        return [num for num in range(n + 1) if sieve[num]]

# 运行命令
# manim -pql your_script.py TrialDivision --numbers_to_check [31, 55, 91]
    def generate_primes(self, n):
        """生成小于等于 n 的所有质数"""
        sieve = [True] * (n + 1)
        sieve[0] = sieve[1] = False
        for start in range(2, int(n**0.5) + 1):
            if sieve[start]:
                for multiple in range(start*start, n + 1, start):
                    sieve[multiple] = False
        return [num for num in range(n + 1) if sieve[num]]

# 运行命令
# manim -pql your_script.py TrialDivision --numbers_to_check [31, 55, 91]

class PrimeNumberScene(Scene):
    def construct(self):
        # 创建自定义 LaTeX 模板
        tex_template = TexTemplate()
        tex_template.add_to_preamble(r"\usepackage{ctex}")        
        # 这里将添加动画元素
        title = Text("什么是质数？")
        definition = Text("质数是指在大于1的自然数中，除了1和它本身之外，不能被其他自然数整除的数。", font_size=24)
        example = MathTex(r"\text{例如：} 2=1 \times 2, 3=1 \times 3", tex_template=tex_template).next_to(title, DOWN)
        self.play(Write(title))
        # title向上移动2秒
        self.play(title.animate.shift(UP))
        self.wait(1)
        self.play(FadeIn(definition), run_time=2)
        self.wait(1)
        self.play(Write(example), run_time=2)    
        self.wait(1)    
        non_prime_example = MathTex(r"\text{非质数：} 4 = 2 \times 2 , 6 = 2 \times 3", tex_template=tex_template).next_to(example, DOWN)
        self.play(Write(non_prime_example))
        self.wait(1)
        
